#ifndef COLLADA_ELEMENT_H_
#define COLLADA_ELEMENT_H_

#define DECLARE_ELEMENT( className ) \
public : \
	static Element*		Create( const char* id, const char* name, Element* pParent, const void* desc ); \
	void				AllChildElementsLoaded( Element* pParent ); \
	void				Initialize( Element* pParent, const void* desc ); \
private : \
	static bool			IsValid( const void* desc ); \
	static std::map< ID, boost::function< Element* ( const char*, const char*, Element*, const void* ) > > _childElements; \


#define IMPLEMENT_ELEMENT( className ) \
std::map< ID, boost::function< Element* (  const char*, const char*, Element*, const void* ) > > className##::_childElements; \
Collada::Element* className##::Create( \
	const char* id, \
	const char* name, \
	Collada::Element* pParent, \
	const void* desc ) \
{ \
	if( !##className##::IsValid( desc ) ) \
	{ \
		assert( false && "Wrong format!!!" ); \
		return NULL; \
	} \
	className##* pThis = new className##( ( id )? id : "", ( name )? name : "" ); \
	if( pThis == NULL ) \
	{ \
		return NULL; \
	} \
	pThis->Initialize( pParent, desc ); \
	TiXmlElement* pChildElem = ( ( TiXmlElement* )desc )->FirstChildElement(); \
	for( ; pChildElem; pChildElem = pChildElem->NextSiblingElement() ) \
	{ \
		const char* id				= pChildElem->Attribute( "id" ); \
		const char* name			= pChildElem->Attribute( "name" ); \
		Fundamental::ID elementID	= Fundamental::JenkinsPHF( pChildElem->Value() ); \
		Element* pChild = ( className##::_childElements[ elementID ] )( id, name, pThis, pChildElem ); \
	} \
	pThis->AllChildElementsLoaded( pParent ); \
	if( pThis->IsNotNeededAnymore() ) \
	{ \
		delete pThis; \
		return NULL; \
	} \
	return pThis; \
} \

#define CHILD_ELEMENT_BEGIN() \
if( _childElements.empty() ) \
{ \

#define CHILD_ELEMENT( elementName, className ) \
	_childElements[ Fundamental::JenkinsPHF( elementName ) ] = &className##::Create;

#define CHILD_ELEMENT_END() \
} \

namespace Collada
{

	class Element : public Fundamental::Object
	{
	DECLARE_RTTI( Collada::Element, Fundamental::Object );

	public :
		static Element*		Create( const char* id, const char* name, Element* pParent, const void* desc );
		virtual void		AllChildElementsLoaded( Element* pParent ) = 0;
		virtual void		Initialize( Element* pParent, const void* desc ) = 0;
	private :
		static bool			IsValid( const void* desc );
		static std::map< ID, boost::function< Element* ( const void* ) > > _childElements; 

	public :
		virtual ~Element();

		ID						GetID(){ return _hashedId; }
		const std::string		GetStringID(){ return _id; }

		bool					IsNotNeededAnymore(){ return _isNotNeededAnymore; }

	protected :
		Element( const std::string& id, const std::string& name );

		bool					_isNotNeededAnymore;

	private :
		ID						_hashedId;
		const std::string		_id;
	};

};

#endif